import annation.Autowrid;
import annation.ComponentScan;
import annation.Componnent;
import annation.Scope;
import bean.DefBean;
import cn.hutool.core.util.ObjectUtil;
import inr.Aware;
import inr.BeanPostAware;
import org.test.Appconfig;

import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;


@Componnent("annonSpringContext")
@Scope("single")
public class AnnonSpringContext {

    private Class objectClass;

    static Map<String, DefBean> map = new HashMap<String, DefBean>();
    static Map<String, Object> singleMap = new HashMap<String, Object>();

    public AnnonSpringContext() {
        boolean annotationPresent = Appconfig.class.isAnnotationPresent(ComponentScan.class);
        ComponentScan annotation = Appconfig.class.getAnnotation(ComponentScan.class);
        String value = annotation.value();
        value = value.replace(".", "/");
        ClassLoader classLoader = Appconfig.class.getClassLoader();
        URL resource = classLoader.getResource(value);
        System.out.println(resource);
        String file = resource.getFile();
        System.out.println("file" + file);
        File f = new File(file);
        String[] list = f.list();
        for (int i = 0; i < list.length; i++) {
            System.out.println(list[i]);
            String className = list[i].substring(0, list[i].indexOf("."));
            try {
                Class<?> aClass = classLoader.loadClass("org.test." + className);
                boolean annotationPresent1 = aClass.isAnnotationPresent(Componnent.class);
                //如果是bean就在判断是否是单例
                if (annotationPresent1) {
                    Componnent componnent11 = aClass.getAnnotation(Componnent.class);
                    //  如果类的名字没有写出来，直接把类名小写
                    String beanName = componnent11.value();

                    if (ObjectUtil.isEmpty(beanName)) {
                        beanName = Introspector.decapitalize(className);
                    }

                    DefBean defBean = new DefBean();
                    Scope scope = aClass.getAnnotation(Scope.class);
                    if (ObjectUtil.isEmpty(scope)  || ObjectUtil.equal("single",scope.value())) {
                        defBean.setScope("single");
                    } else {
                        defBean.setScope("prototype");
                    }



                    Autowrid autowrid = aClass.getAnnotation(Autowrid.class);


                    defBean.setBeanName(beanName);
                    defBean.setType(aClass);
                    map.put(beanName, defBean);


                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        Set<String> keySet = map.keySet();
        //bean的前置处理

        for (String set : keySet) {
            DefBean defBean = map.get(set);
            Object createbean = this.createbean(defBean.getBeanName(), defBean);
            if(createbean instanceof BeanPostAware){
                ((BeanPostAware) createbean).before(set,defBean);
            }



        }

        // 单例对象放入到单例池子中去

        for (String set : keySet) {
            DefBean defBean = map.get(set);


            if (ObjectUtil.equal(defBean.getScope(), "single")) {
                Class<? extends DefBean> aClass = defBean.getType();
                try {
                    Object defBean1 = aClass.newInstance();
                    if(defBean1 instanceof Aware){
                        ((Aware) defBean1).setBeanName(defBean.getBeanName());
                    }
                    singleMap.put(defBean.getBeanName(), defBean1);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }


        //依赖注入实现
        for (String set : keySet) {
            DefBean defBean = map.get(set);
            Class type = defBean.getType();
            Object aClass = this.createbean(defBean.getBeanName(), defBean);


            for (int j = 0; j < type.getDeclaredFields().length; j++) {
                Field field = type.getDeclaredFields()[j];
                boolean isPresent = field.isAnnotationPresent(Autowrid.class);
                if (isPresent) {
                    field.setAccessible(true);


                    try {
                        field.set(aClass, getBean(field.getName()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        }

    }


    private Object createbean(String beanName,DefBean defBean){
        //创建后 ，放入到单例池子中去
        Class<? extends DefBean> aClass = defBean.getType();
        Object o = singleMap.get(beanName);
        if(ObjectUtil.isNotEmpty(o)){
            return o;
        }


        try {
            Object defBean1 = aClass.newInstance();
            return defBean1;
        } catch (Exception e) {
            e.printStackTrace();
        }
   return null;
    }

    public Object getBean(String beanName) {
        DefBean defBean = map.get(beanName);
        if (ObjectUtil.isEmpty(defBean)) {

            throw new RuntimeException("没有这个bean");
        } else {
            String scope = defBean.getScope();
            if (ObjectUtil.equal(scope, "single")) {
                Object o = singleMap.get(beanName);
                if(ObjectUtil.isEmpty(o)){
                   o=map.get(beanName);

                }
                if(ObjectUtil.isEmpty(o)){

                 o=createbean(beanName,defBean);
                }
                singleMap.put(beanName,o);
                return o;

            } else {
                //创建后 ，放入到单例池子中去
                Class<? extends DefBean> aClass = defBean.getType();
                try {
                    Object defBean1 = aClass.newInstance();
                    return defBean1;
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
        return null;
    }

}
